#pragma region Description
/*
     Copyright © 2011 Jesse 'LorgonJortle' Wilkerson
     See licensing in source (.cpp) file, or at:
     <http://www.gnu.org/licenses/> (GPL)

     File: Matrix.h
     Author: Jesse 'LorgonJortle' Wilkerson
     Description:
          Matrices are the gears of 3D applications.
          In order to get shader to work, 3D objects
          to display, and cameras to move, we need
          matrices. This class is capable of being
          dynamically resized to match any dimension
          the programmer may need.
*/
#pragma endregion

#ifndef MATRIX_H
#define MATRIX_H

/*****************************************
                              OpenGL
*****************************************/
     #ifdef __APPLE__
         #include <glew.h>
     #else
         #include <GL/glew.h>
     #endif
/****************************************/

/*****************************************
                         Standard C++
*****************************************/
     #include <iostream>
     #include <vector>
     #include <string>
     #include <sstream>
/****************************************/

/*****************************************
                         LOGL::GLib
*****************************************/
     /*****************************************
                                   Math
     *****************************************/
          #include "Math.h"
/****************************************/

/*
     Identity:           Translation:        Constuct:
          1 0 0 0             1 0 0 x                  x y z X
          0 1 0 0             0 1 0 y                  x y z Y
          0 0 1 0             0 0 1 z                  x y z Z
          0 0 0 1             0 0 0 1                  0 0 0 1

*/

namespace LOGL_GLib
{
     namespace Common
     {
          class Matrix
          {
               public:
                    /* Constructs a matrix object. */
                    Matrix();
                    /* Destructs the matrix, releasing any indebted resources. */
                    ~Matrix();

                    /* Accesses the specified column in the matrix. */
                    GLfloat* operator [](GLint _Index);

                    /* Gets the width of the matrix. */
                    GLint Width() const;
                    /* Gets the height of the matrix. */
                    GLint Height() const;

                    /* Adds a row (of the current width) to the matrix. */
                    GLboolean AddRow(GLfloat _Value = 0.0f);
                    /* Adds a row of the specified values (of the current width) to the matrix. */
                    GLboolean AddRow(GLfloat* _Values, GLint _Size);
                    /* Adds a column (of the current height) to the matrix. */
                    GLboolean AddColumn(GLfloat _Value = 0.0f);
                    /* Adds a column of the specified values (of the current height) to the matrix. */
                    GLboolean AddColumn(GLfloat* _Values, GLint _Size);
                    /* Removes a row from the matrix. */
                    GLvoid RemoveRow();
                    /* Removes a column from the matrix. */
                    GLvoid RemoveColumn();
                    /* Assigns the specified data to the matrix. */
                    GLvoid Assign(GLfloat* _Data, GLuint _Size);
                    /* Assigns the specified data to the matrix. */
                    GLvoid Assign(std::vector<GLfloat>& _Data);

                    /* Assigns this to the identity matrix. */
                    GLvoid Identity();
                    /* Calculates an identity matrix. */
                    static Matrix CreateIdentity();
                    /* Assigns this to the zero matrix. */
                    GLvoid Zero(GLint _Width = 4, GLint _Height = 4);
                    /* Calculates a zero matrix. */
                    static Matrix CreateZero(GLint _Width = 4, GLint _Height = 4);

                    /* Calculates a perspective view frustum with the specified dimensions. */
                    static Matrix CreatePerspectiveProjection(GLfloat _Left, GLfloat _Right, GLfloat _Bottom, GLfloat _Top, GLfloat _Near, GLfloat _Far);
                    static Matrix CreatePerspectiveProjection(GLfloat _FOV, GLfloat _AspectRatio, GLfloat _Near, GLfloat _Far);
                    /* Calculates an orthographic view frustum with the specified dimensions. */
                    static Matrix CreateOrthoProjection(GLfloat _Left, GLfloat _Right, GLfloat _Bottom, GLfloat _Top, GLfloat _Near, GLfloat _Far);
                    /* Calculates a translation matrix from the specified point. */
                    static Matrix CreateTranslation(const Vector3& _Translation);
                    /* Calculates a scale matrix from the specified scale ratios. */
                    static Matrix CreateScale(const Vector3& _Scale);
                    /* Calculates a rotation matrix around the X axis of the following radians. */
                    static Matrix CreateRotationX(GLfloat _Radians);
                    /* Calculates a rotation matrix around the Y axis of the following radians. */
                    static Matrix CreateRotationY(GLfloat _Radians);
                    /* Calculates a rotation matrix around the Z axis of the following radians. */
                    static Matrix CreateRotationZ(GLfloat _Radians);

                    /* Translates this matrix by the specified vector. */
                    GLvoid Translate(const Vector3& _Translation);
                    /* Scales this matrix by the specified vector. */
                    GLvoid Scale(const Vector3& _Scale);
                    /* Rotates this matrix around the X axis by the specified vector. */
                    GLvoid RotateX(GLfloat _Radians);
                    /* Rotates this matrix around the Y axis by the specified vector. */
                    GLvoid RotateY(GLfloat _Radians);
                    /* Rotates this matrix around the Z axis by the specified vector. */
                    GLvoid RotateZ(GLfloat _Radians);

                    /* Calculates the negated version of this. */
                    Matrix operator -();
                    /* Adds the specified matrix with this. */
                    Matrix operator +(Matrix& _Mat);
                    /* Adds the specified matrix to this. */
                    GLvoid operator +=(Matrix& _Mat);
                    /* Subtracts the specified matrix and this. */
                    Matrix operator -(Matrix& _Mat);
                    /* Subtracts the specified matrix from this. */
                    GLvoid operator -=(Matrix& _Mat);
                    /* Scales the matrix. */
                    Matrix operator *(GLfloat _Scalar);
                    /* Scales this matrix. */
                    GLvoid operator *=(GLfloat _Scalar);
                    /* Calculates the product of two matrices. */
                    Matrix operator *(Matrix& _Mat);
                    /* Multiplies the specified matrix onto this. */
                    GLvoid operator *=(Matrix& _Mat);

                    /* Converts the matrix into string format. */
                    std::string ToString();


               private:
                    /* The actual float data of the matrix. */
                    std::vector<GLfloat> data;
                    /* The width of the matrix. */
                    GLint width;
                    /* The height of the matrix. */
                    GLint height;

          }; /* Class Matrix. */
     } /* Namespace Common. */
} /* Namespace LOGL_GLib. */

#endif
